home *** CD-ROM | disk | FTP | other *** search
- /*
- Functions for date calculation and conversion. Inspired by DATE.C from
- John A. Hodgson, and a need for date calculation routines in an upcoming
- project. These routines should be error-free until the beginning of the
- 22nd century. Please see the text above each routine for notes and comments
- on usage. I've spent much time developing and testing these routines.
-
- */
-
-
- typedef struct JULDATE {
- short year;
- short days;
- };
-
- short days_before[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
- /* # of days preceding each month */
-
- /*
- The following routine accepts one argument, a pointer to a JULDATE
- structure. It returns the current date in Julian date form.
- */
-
- void Get_Date(date)
- struct JULDATE *date;
- {
- long datestmp[3];
- int junk, year_span, years_left, remainder, leapdays;
-
- junk = DateStamp(&datestmp[0]); /* get the date */
- datestmp[0] += 1; /* add 1 for Jan. 1, 1978 */
- year_span = datestmp[0] / 366; /* approx. year */
- date->days = datestmp[0] % 366; /* # of days left over */
- leapdays = year_span / 4; /* approx. # of leap days */
- date->year = 1978 + year_span; /* current year */
- years_left = year_span % 4; /* years since last leap yr */
- remainder = date->year % 4; /* # of years since last leap */
- if (remainder <= years_left && remainder > 0)
- leapdays += 1; /* recent year was a leap year */
- date->days += year_span - leapdays; /* correct for leap days */
- if (remainder > 0 && date->days > 365)
- {
- date->year += 1;
- date->days -= 365;
- }
- else if (remainder == 0 && date->days > 366)
- {
- date->year += 1;
- date->days -= 366;
- }
- }
-
- /*
- This function accepts two arguments: a string pointer and a pointer to a
- JULDATE structure. The routine will convert the Julian date to Gregorian
- (mm-dd-yyyy) format. The string pointer must point to a space at least
- 11 characters long.
- */
-
- void JultoGreg(greg_date, date)
- char *greg_date;
- struct JULDATE *date;
- {
- int length, year, month, day;
- short julday;
- char string[6];
-
- year = date->year;
- julday = date->days;
- if ( !(year % 4) && julday > 60) julday -= 1;
- /* subtract 1 if we are in a leap year & past Feb. */
- for (month = 0; (days_before[month] < julday) && (month < 12); month++);
- /* find month */
- day = julday - days_before[month-1]; /* get current day */
- length = stci_d(greg_date, month, 11); /* month into greg_date */
- strcat(greg_date, "-");
- length = stci_d(string, day, 6);
- strcat(greg_date, string); /* add day to greg_date */
- strcat(greg_date, "-");
- length = stci_d(string, year, 6);
- strcat(greg_date, string); /* add year to greg_date */
- }
-
- /*
- The following function accepts two arguments: A pointer to a JULDATE
- structure and a pointer to a string. It evaluates the string to determine
- if it is a valid date, then converts it to Julian form and returns the
- value in the JULDATE structure. If the date is invalid, the year element
- of the JULDATE structure will be 0. It is not 100% accurate in its date-
- checking, as it only checks to make sure that the date is not greater than
- 31, without checking what the maximum value should be for that month. The
- Julian date returned *will* be valid, however, if not correct.
-
- NOTE: The Gregorian date passed to this routine can be in mm-dd-yy OR
- mm-dd-yyyy form. The century will automatically be added if the
- form is the former. (no pun intended)
- */
-
- void GregtoJul(date, greg_date)
- struct JULDATE *date;
- char *greg_date;
- {
- extern char *stpblk(); /* standard string functions that */
- /* strips leading spaces */
- int month, day, year;
- short count;
- char *stptr;
-
- date->year = 0; /* will be 0 if date invalid */
- stptr = stpblk(greg_date); /* advance past any blanks */
- count = stcd_i(stptr, &month); /* extract month # */
- stptr += count;
- if ( (stptr[0] == '-' || stptr[0] == '/') && month >= 1 && month <= 12)
- {
- stptr += 1; /* skip delimiter */
- count = stcd_i(stptr, &day);
- stptr += count;
- if ((stptr[0] == '-' || stptr[0] == '/') && day >=1 && day <=31)
- {
- stptr += 1; /* skip delimiter */
- count = stcd_i(stptr, &year);
- if ( year > 0 )
- {
- if ( year < 100 )
- year += 1900; /* only got 2 digits */
- date->year = year;
- date->days = days_before[month - 1];
- date->days += day;
- if (!(year % 4) && month > 2) /* > Feb */
- date->days += 1; /* leap year */
- }
- }
- }
- }
-
- /*
- The following function accepts two arguments, both pointers to JULDATE
- structures. The routine calculates the number of days between the two
- dates and returns the result as an integer. If the first date is earlier
- than the second, the value returned will be positive. If the second date
- is earlier than the first, the value returned will be negative.
-
- NOTE TO 8/16 BIT USERS: int on the Amiga (and presumably any 16/32 bit
- machine) declares a 32-bit integer. I use int here for clarity, but if
- the default size of int on your machine is 16-bit, you will have to
- declare days1 & days2 as long.
- */
-
- int Date_Span(date1, date2)
- struct JULDATE *date1, *date2;
- {
- int days1, days2;
-
- days1 = (date1->year - 1) * 365 + (date1->year - 1) / 4 + date1->days;
- days2 = (date2->year - 1) * 365 + (date2->year - 1) / 4 + date2->days;
- return (days2 - days1);
- }
-
- /*
- The following function accepts a pointer to a JULDATE structure and
- returns an integer that is the current day of the month. It also assigns
- to num the number of days in the current month, and to mn the month #.
- */
-
- int Datestat(date, num, mn)
- struct JULDATE *date;
- int *num, *mn;
- {
- int month;
- short julday;
-
- julday = date->days;
- if (date->year % 4 == 0 && julday > 60) julday -= 1;
- for (month = 0; (days_before[month] < julday) && (month < 12); month++);
- /* find month */
- if (month == 12)
- *num = 31;
- else
- {
- *num = days_before[month] - days_before[month - 1];
- if (date->year % 4 == 0 && month == 2)
- *num += 1;
- }
- *mn = month;
- return(julday - days_before[month-1]);
- }
-